package com.example.futureai.service.impl;

import cn.hutool.core.util.StrUtil;
import com.example.futureai.constants.SpringAIConst;
import com.example.futureai.dto.ChatDto;
import com.example.futureai.dto.DocVtsDto;
import com.example.futureai.dto.SendMsgDto;
import com.example.futureai.eum.ChatTYpe;
import com.example.futureai.service.CharRecordService;
import com.example.futureai.service.ChatService;
import com.example.futureai.utils.ChatUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.filter.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

/**
 * @ClassName: ChatServiceImpl
 * @Description:
 * @Author: YourName
 * @Date: 2025/2/26
 */

@Slf4j
@Service
public class ChatServiceImpl implements ChatService {/*
*//*
    @Autowired
    @Qualifier("myVectorStore")
    private VectorStore vectorStore;
*//*

//    @Autowired
//    @Qualifier("myChatModel")
//    private OpenAiChatModel chatModel;

   *//* @Autowired
    @Qualifier("myOllamaChatModel")
    private OllamaChatModel chatModel;
*//*
    @Autowired
    private CharRecordService charRecordService;


    @Override
    public Flux<ServerSentEvent<ChatDto>> memoryStreamWithApi( SendMsgDto sendMsgDto) {
        return serverSentEventFlux(sendMsgDto);

//        // 获取匹配文档
//        List<DocVtsDto> matchtoFiles = getMatchtoFiles(sendMsgDto);
//        // 如果匹配到文档则根据文档进行 回答
//        if (CollectionUtils.isEmpty(matchtoFiles)) {
//            return serverSentEventFlux(sendMsgDto);
//        } else {
//            sendMsgDto.setFiles(matchtoFiles);
//            return serverSentEventFluxByDoc(sendMsgDto);
//        }
    }

    public ChatClient.ChatClientRequestSpec bulidRequest(SendMsgDto sendMsgDto) {

        String defaultSystem = ChatTYpe.getChatTYpe(sendMsgDto.getChatType()).getDefaultSystem();
        return ChatClient.builder(chatModel)
                .defaultSystem(defaultSystem)
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(new InMemoryChatMemory()))

                .build()
                .prompt()
                .user(sendMsgDto.getInputInfo())
                .advisors(advisor -> advisor.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sendMsgDto.getAccessKey()).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 5));
    }


    @Override
    public List<DocVtsDto> getMatchtoFiles(SendMsgDto sendMsgDto) {
        SearchRequest searchRequest = buildSearchRequest(sendMsgDto);
        //查询匹配到的文档内容
        List<Document> documents = vectorStore.similaritySearch(searchRequest);
        //组装返回的文档信息
        List<DocVtsDto> matchtoFileList = new ArrayList<>();
        documents.forEach(document -> {
            Map<String, Object> metadata = document.getMetadata();
            DocVtsDto docVtsDto = new DocVtsDto();
            docVtsDto.setDocId((String) metadata.get(SpringAIConst.VectorStore.METADATA_DOC_ID));
            docVtsDto.setDocName((String) metadata.get(SpringAIConst.VectorStore.METADATA_DOC_NAME));
            matchtoFileList.add(docVtsDto);
        });
        return matchtoFileList;
    }



    public Flux<ServerSentEvent<ChatDto>> serverSentEventFlux(SendMsgDto sendMsgDto) {
        StringBuilder fullResponse = new StringBuilder();
        return bulidRequest(sendMsgDto)
                .stream()
                .chatResponse()
                .map(response -> {
                    // 创建自定义响应对象
                    ChatDto customResponse = new ChatDto(sendMsgDto.getMsgId(), ChatUtil.CHAT_TYPE_AI, ChatTYpe.TEXT.getType(), response.getResult().getOutput().getText(), new ArrayList<>());
                    fullResponse.append(response.getResult().getOutput().getText());
                    return ServerSentEvent.<ChatDto>builder()
                            .data(customResponse)
                            .build();
                })
                .concatWith(Flux.just(
                        ServerSentEvent.<ChatDto>builder()
                                .data(new ChatDto(sendMsgDto.getMsgId(), ChatUtil.CHAT_TYPE_AI, ChatTYpe.TEXT.getType(),"[DONE]", new ArrayList<>())) // 结束标志
                                .build()
                )).doOnComplete(() -> {
                    // 流结束后异步保存完整响应到数据库
                    charRecordService.saveCharRecord(fullResponse.toString(), sendMsgDto);
                });
    }

    public Flux<ServerSentEvent<ChatDto>> serverSentEventFluxByDoc(SendMsgDto sendMsgDto) {
        SearchRequest searchRequest = buildSearchRequest(sendMsgDto);
        StringBuilder fullResponse = new StringBuilder();
        return bulidRequest(sendMsgDto)
//                .advisors(new QuestionAnswerAdvisor(vectorStore, searchRequest))
                .stream()
                .chatResponse()
                .map(response -> {
                    // 创建自定义响应对象
                    ChatDto customResponse = new ChatDto(sendMsgDto.getMsgId(), ChatUtil.CHAT_TYPE_AI, ChatTYpe.TEXT.getType(),response.getResult().getOutput().getText(), new ArrayList<>());
                    fullResponse.append(response.getResult().getOutput().getText());
                    return ServerSentEvent.<ChatDto>builder()
                            .data(customResponse)
                            .build();
                })
                .concatWith(Flux.just(
                        ServerSentEvent.<ChatDto>builder()
                                .data(new ChatDto(sendMsgDto.getMsgId(), ChatUtil.CHAT_TYPE_AI, ChatTYpe.TEXT.getType(),"[DONE]", sendMsgDto.getFiles())) // 结束标志
                                .build()
                )).doOnComplete(() -> {
                    // 流结束后异步保存完整响应到数据库
                    charRecordService.saveCharRecord(fullResponse.toString(), sendMsgDto);
                });
    }


    public SearchRequest buildSearchRequest(SendMsgDto sendMsgDto) {
        if (StrUtil.isNotEmpty(sendMsgDto.getDocIds())) {
            // 组装过滤条件，根据文档ID过滤，等价于 SQL 的 WHERE docId IN (docId1,docId2...)
            List<String> docIdList = Arrays.asList(sendMsgDto.getDocIds().split(","));
            Filter.Expression expression = new Filter.Expression(
                    Filter.ExpressionType.IN,
                    new Filter.Key(SpringAIConst.VectorStore.METADATA_DOC_ID),
                    new Filter.Value(docIdList)
            );
            return SearchRequest.builder().query(sendMsgDto.getInputInfo())
                    .filterExpression(expression)
                    .topK(6)
                    .similarityThreshold(0.8d).build();
        } else {
            return SearchRequest.builder().query(sendMsgDto.getInputInfo()).topK(6).similarityThreshold(0.8d).build();
        }
    }
*/}
